"""
文件上传下载功能
"""

import socket
import struct
import json
import os

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(("127.0.0.1", 8080))
server.listen(5)  # 5代表最大挂起的连接数

print("ssh starting...")
while True:  # 链接循环
    # 建立链接
    conn, client_addr = server.accept()
    print(f"[client_addr]: {client_addr}")
    # 进行通讯
    while True:  # 通信循环
        try:  # 针对Windows系统，接收空字符串的处理方法
            # 1. 接收命令
            ret = conn.recv(8096)  # Windows系统会在这里抛出错误
            # 客户端不允许发送空字符串
            if not ret:  # 针对linux系统，接收空字符串的处理方法
                break
            print(f"[client data] : {ret.decode('utf-8')}")
            # 2. 解析命令，提取参数
            cmds = ret.decode('utf-8').split()
            filename = cmds[1]
            # 3. 以读的方式打开文件
            # 第1步: 制作固定长的报头
            header_dict = {
                "filename": filename,
                "md5": "111111",
                "total_size": os.path.getsize(filename)
            }
            header_json = json.dumps(header_dict)
            header_bytes = header_json.encode("utf-8")
            # 第2步: 发送报头长度
            header_len = struct.pack("i", len(header_bytes))
            conn.send(header_len)
            # 第3步: 发送报头
            conn.send(header_bytes)
            # 第4步: 发送数据
            with open(filename, 'rb') as f:
                print(f"open file {filename}")
                # conn.send(f.read())
                for line in f:
                    conn.send(line)
            print(f"send file {filename} success")
        except ConnectionResetError:
            break

    # 6. 挂电话
    conn.close()

# 7. 关机
server.close()
